﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.ComponentModel;

namespace Components
{
    public partial class ImagedTextBox : System.Web.UI.UserControl
    {
        private HtmlGenericControl[] previewHolders;

        [TypeConverter(typeof(StringArrayConverter))]
        public string[] Formats { get; set; }

        /// <summary>
        /// 获取或设置图片的最大大小（KB）。
        /// </summary>
        public long MaxImageSize { get; set; }

        public int MaxImageCount { get; set; }

        public string CssClassForItemLabel { get; set; }


        protected void Page_Load(object sender, EventArgs e)
        {
            AddCssLink();

            if (string.IsNullOrEmpty(CssClassForItemLabel) == false)
                itemLabel.Attributes["class"] = CssClassForItemLabel;

            //Formats
            if (Formats.Length == 0)
            {
                acceptableFormatsLabel.Text = Formats[0];
            }
            else if (Formats.Length == 2)
                acceptableFormatsLabel.Text = Formats[0] + " and " + Formats[1];
            else if (Formats.Length > 2)
            {
                for (int i = 0; i < Formats.Length - 1; i++)
                {
                    acceptableFormatsLabel.Text += Formats[i] + ", ";
                }
                acceptableFormatsLabel.Text += "and " + Formats[Formats.Length - 1];
            }




            //MaxImageSize
            if (MaxImageSize > 0)
                fileSizeLabel.Text = MaxImageSize + " KB";
            else
                fileSizeLabel.Text = "infinite";


            //只能在Load事件中注册事件处理函数！！！
            /*
         * 图片显示逻辑：
         * 1、在Load事件中创建全部的图片占位符，并注册事件处理函数。所有的占位符Visible=false。
         * 2、在控件事件中操作Session。
         * 3、在OnPreRender方法中显示图片占位符的内容，显示所需的占位符。
         */
            previewHolders = new HtmlGenericControl[MaxImageCount];
            for (int i = 0; i < MaxImageCount; i++)
            {
                var previewHolder = new HtmlGenericControl();
                previewHolder.EnableViewState = true;//必须为true，因为其子控件deleteButton需要视图状态保存CommandArgument。
                previewHolder.TagName = "div";
                previewHolder.Visible = false;
                previewHolder.Attributes.Add("class", "previewHolder");

            
                Image img = new Image();
                img.CssClass = "preview";
                img.EnableViewState = false;
            
                previewHolder.Controls.Add(img);

                Button deleteButton = new Button();
                deleteButton.Text = "Delete";
                deleteButton.Command += new CommandEventHandler(deleteButton_Command);
                previewHolder.Controls.Add(deleteButton);

                imageContainer.Controls.Add(previewHolder);
                previewHolders[i] = previewHolder;
            }
        }

        void deleteButton_Command(object sender, CommandEventArgs e)
        {
            Contract.Assert(Session[SessionKeys.PreviewingImages] != null);//以为必然先Upload，在Delete。
            ((IList<RawImage>)Session[SessionKeys.PreviewingImages]).RemoveAt(Convert.ToInt32(e.CommandArgument));
        }


        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (Session[SessionKeys.PreviewingImages] == null)
                return;
            IList<RawImage> imageList = (IList<RawImage>)Session[SessionKeys.PreviewingImages];
            for (int i = 0; i < previewHolders.Length; i++)
            {
                if (i < imageList.Count)
                {
                    ((Image)previewHolders[i].Controls[0]).ImageUrl =ResolveUrl("~/Picture.aspx?src=session&id=" + i);
                    ((Button)previewHolders[i].Controls[1]).CommandArgument = i.ToString();
                    previewHolders[i].Visible = true;
                }
                else
                {
                    ((Image)previewHolders[i].Controls[0]).ImageUrl = string.Empty;
                    ((Button)previewHolders[i].Controls[1]).CommandArgument = string.Empty;
                    previewHolders[i].Visible = false;
                }
            }


            //MaxImageCount
            var t = Session[SessionKeys.PreviewingImages] as IList<RawImage>;
            uploadButton.Enabled = t == null || t.Count < MaxImageCount;
        }

        protected void fileFormatValidator_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = false;
            foreach (var format in Formats)
            {
                if (FileUpload.FileName.EndsWith(format, StringComparison.OrdinalIgnoreCase))
                {
                    args.IsValid = true;
                    break;
                }
            }

            if (args.IsValid == false)
            {
                string classValue = fileFormatConstraintLabel.Attributes["class"];
                if (string.IsNullOrEmpty(classValue))
                    fileFormatConstraintLabel.Attributes.Add("class", "errorText");
                else
                    fileFormatConstraintLabel.Attributes["class"] = classValue + " errorText";
            }
            Debug.Assert(fileFormatConstraintLabel.EnableViewState == false);
            //else
            //{
            //    string classValue = fileFormatConstraintLabel.Attributes["class"];
            //    if (string.IsNullOrEmpty(classValue) == false)
            //        fileFormatConstraintLabel.Attributes["class"] = classValue.Replace(" errorText", string.Empty);
            //}
        }

        protected void fileSizeValidator_ServerValidate(object source, ServerValidateEventArgs args)
        {
            args.IsValid = FileUpload.PostedFile.ContentLength <= MaxImageSize * 1024;

            if (args.IsValid == false)
            {
                string classValue = fileSizeConstraintLabel.Attributes["class"];
                if (string.IsNullOrEmpty(classValue))
                    fileSizeConstraintLabel.Attributes.Add("class", "errorText");
                else
                    fileSizeConstraintLabel.Attributes["class"] = classValue + " errorText";
            }
            Debug.Assert(fileSizeConstraintLabel.EnableViewState == false);
            //else
            //{
            //    string classValue = fileSizeConstraintLabel.Attributes["class"];
            //    if (string.IsNullOrEmpty(classValue) == false)
            //        fileSizeConstraintLabel.Attributes["class"] = classValue.Replace(" errorText", string.Empty);
            //}

        }

        protected void uploadButton_Click(object sender, EventArgs e)
        {
            if (Page.IsValid == false)
                return;

            List<RawImage> imageData;
            if (Session[SessionKeys.PreviewingImages] == null)
            {
                imageData = new List<RawImage>(MaxImageCount);
                Session[SessionKeys.PreviewingImages] = imageData;
            }
            else
                imageData = (List<RawImage>)Session[SessionKeys.PreviewingImages];

            byte[] data = new byte[FileUpload.PostedFile.ContentLength];
            FileUpload.PostedFile.InputStream.Read(data, 0, data.Length);
            FileUpload.PostedFile.InputStream.Close();

            imageData.Add(new RawImage(data, FileUpload.PostedFile.ContentType));
        }


        private void AddCssLink()
        {
            var controls = Page.Header.Controls.OfType<HtmlLink>().ToArray();

            string href = ResolveUrl("~/Styles/ImagedTextBox.css");
            for (int i = 0; i < controls.Length; i++)
            {
                if (controls[i].Href == href)
                    return;
            }

            var link = new HtmlLink { Href = href };
            link.Attributes.Add("rel", "stylesheet");
            link.Attributes.Add("type", "text/css");
            Page.Header.Controls.Add(link);
        }
    }
}